# -*- coding: utf-8 -*-
import json
import re

from django.conf import settings
from django.http import HttpResponse
from django.utils.deprecation import MiddlewareMixin
from rest_framework import status

from demo.demo_logging_mgmt.serializers import UserActionLogSerializer
from demo_common_module.utils.cache_utils import CacheUtils


class UserActionsLog(MiddlewareMixin):

    def check_search_path(self, request_path):
        # 系统层面不进行处理的path
        not_process_paths = [
            '/swagger/', '/redoc/', '/admin/', '/user/info/',
        ]

        # 数据层面补进行处理的PATH处理
        temp_not_process_paths = ['/budget/generate/status/', '/data/bom/classFirst/', '/data/bom/proportion/',
                                  '/data/paper/gram/', '/data/plant/line/', '/planning/bom/price/',
                                  '/planning/paper/gram/', '/planning/plant/info/', '/planning/plant/line/',
                                  '/planning/status/info/']

        not_process_paths += temp_not_process_paths

        not_process_paths = [f'({not_process_path})' for not_process_path in not_process_paths]
        re_path = '|'.join(not_process_paths)
        # 如果匹配到内容，表示对该path不进行处理
        search_path = re.search(r'{}'.format(re_path), request_path)
        if not search_path:
            return False
        return True

    def get_cache_user_role(self, token):
        try:
            cache_utils = CacheUtils()
            cache_user_info = cache_utils.get_user_info(token)
            role_names = cache_user_info.get('role_names', [])  # 获取角色列表
            permission_url_method_dict = cache_user_info.get('permission_url_method_dict', {})  # 获取权限url与方法的字典表
        except Exception:
            error_msg = {'status': 'timeout', 'message': 'The token is invalid, please log in again'}
            err_response = HttpResponse(json.dumps(error_msg), status=status.HTTP_200_OK)
            err_response['content-type'] = 'application/json; charset=utf-8'
            return None, None, err_response

        return role_names, permission_url_method_dict, None

    def get_cache_user_info(self, token):
        try:
            cache_utils = CacheUtils()
            cache_user_info = cache_utils.get_user_info(token)
            user_info = cache_user_info.get('user_info')  # 获取用户信息
            # 重新刷新一下token的时间
            cache_utils.save_user_info(token, cache_user_info)
        except Exception:
            error_msg = {'status': 'timeout', 'message': 'The token is invalid, please log in again'}
            err_response = HttpResponse(json.dumps(error_msg), status=status.HTTP_200_OK)
            err_response['content-type'] = 'application/json; charset=utf-8'
            return None, err_response

        return user_info, None

    def process_request(self, request):
        request_method = request.method.lower()
        request_path = request.path
        token = request.META.get('HTTP_AUTHORIZATION')
        request_path = request_path.replace('/api', '')

        error_msg = dict()
        # 没有匹配到权限放开的url，才会去执行一下逻辑
        if not self.check_search_path(request_path):
            role_names, permission_url_method_dict, err_response = self.get_cache_user_role(token)
            if err_response:
                return err_response

            # 不是admin角色的才需要url鉴权，admin角色不需要url鉴权
            if settings.SYSTEM_SUPER_ROLE not in role_names:
                # 硬匹配
                permission_urls_list = [permission_url for permission_url in permission_url_method_dict.keys()]
                if request_path not in permission_urls_list:
                    error_msg = {'status': 'fail', 'message': '无权限操作，请申请权限！'}
                else:
                    type_names = permission_url_method_dict.get(request_path)
                    if request_method not in type_names:
                        error_msg = {'status': 'fail', 'message': '无权限操作，请申请权限！'}

                if error_msg:
                    response = HttpResponse(json.dumps(error_msg), status=status.HTTP_200_OK)
                    response['content-type'] = 'application/json; charset=utf-8'
                    return response

    def process_response(self, request, response):
        request_method = request.method.lower()
        request_path = request.path
        token = request.META.get('HTTP_AUTHORIZATION')
        request_path = request_path.replace('/api', '')

        if not self.check_search_path(request_path):
            match_obj = request.resolver_match
            path_desc = 'PATH无权限'
            if match_obj:
                path_desc = match_obj.url_name

            user_info, err_response = self.get_cache_user_info(token)
            if err_response:
                return err_response

            # 记录用户的行为
            self.save_user_log(request_method, request_path, user_info, path_desc)
        return response

    def save_user_log(self, request_method, request_path, user_info, path_desc):
        # 对OPTIONS方法不进行处理
        not_process_methods = ['options']
        if request_method not in not_process_methods:
            # 从缓存中获取用户的信息
            user_log = {
                'user_name': user_info.get('user_name'),
                'user_id': user_info.get('user_id'),
                'request_type': request_method,
                'path': request_path,
                'path_desc': path_desc,
            }
            serializer = UserActionLogSerializer(data=user_log)
            serializer.is_valid(raise_exception=True)
            serializer.save()
